﻿using System;
using System.Collections.Generic;

namespace RedNoteModule
{
    /// <summary>
    /// 红点节点
    /// </summary>
    public class RedNote
    {
        public string Key { get; private set; }
        public bool IsRoot => m_parent == null;
        public int ChildrenCount => m_children.Count;

        public bool IsDestroyed { get; private set; }
        
        #region 关系树
        public RedNote Parent => m_parent;
        public IReadOnlyList<RedNote> Children => m_children;

        private RedNote m_parent;
        private List<RedNote> m_children = new List<RedNote>();
        #endregion
        
        public RedNote(string key)
        {
            this.Key = key;
            this.State = false;

            IsDestroyed = false;
        }

        public bool SetParent(RedNote parent)
        {
            if (m_parent == null)
            {
                this.m_parent = parent;
                return true;                
            }
            return false;
        }

        public bool ClearParent()
        {
            m_parent = null;
            return true;
        }
        
        public bool AddChild(RedNote targetKey)
        {
            if (IsSelf(targetKey.Key))
            {
                throw new Exception($"错误：{Key}试图将自身添加为子节点！targetKey:[{targetKey}]");
            }

            if (IsParent(targetKey.Key))
            {
                throw new Exception($"错误：{Key}试图将父节点添加为子节点！targetKey:[{targetKey}]");
            }

            if (IsChildren(targetKey.Key))
            {
                throw new Exception($"错误：{Key}试图重复添加子节点！targetKey:[{targetKey}]");
            }
            
            m_children.Add(targetKey);
            return true;
        }

        public bool RemoveChild(string targetKey)
        {
            if (!IsChildren(targetKey, false))
            {
                return false;
            }

            int removeCnt = m_children.RemoveAll(child => child.Key.Equals(targetKey));
            return removeCnt > 0;
        }

        public bool IsLeafNote()
        {
            return ChildrenCount == 0;
        }

        public bool IsSelf(string targetKey)
        {
            return Key == targetKey;
        }

        public bool IsParent(string targetKey, bool recursive = true)
        {
            if (!recursive)
            {
                return m_parent != null && m_parent.Key == targetKey;
            }
            
            bool flag = false;
            RedNote ptr = m_parent;
            while (ptr != null)
            {
                if (ptr.Key.Equals(targetKey))
                {
                    flag = true;
                    break;
                }
                ptr = ptr.Parent;
            }
            
            return flag;
        }
        
        public bool IsChildren(string targetKey, bool recursive = true)
        {
            bool flag = false;
            for (int i=0; i<m_children.Count && !flag; i++)
            {
                flag |= m_children[i].IsSelf(targetKey) || (recursive && m_children[i].IsChildren(targetKey, true));
            }
            return flag;
        }

        #region 状态
        
        private readonly HashSet<string> m_activeChildren = new HashSet<string>();
        

        public bool State { get; private set; }
        
        public bool SetState(bool active)
        {
            if (!IsLeafNote())
            {
                return false;
            }

            bool beforeState = State;
            State = active;
            
            return beforeState != State;
        }

        public bool AfterChildStateUpdate(string childKey, bool active)
        {
            if (!IsChildren(childKey, false))
            {
                return false;
            }
            
            bool beforeState = State;
            if (active)
            {
                m_activeChildren.Add(childKey);
            }
            else
            {
                m_activeChildren.Remove(childKey);
            }
            State = m_activeChildren.Count > 0;
            return beforeState != State;
        }

        public void Destroy()
        {
            IsDestroyed = true;
        }
        #endregion

    }
}